﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;

namespace SSM.DeepZoomViewer
{
    /// <summary>
    /// 하나의 레벨을 나타내는 클래스
    /// </summary>
    public class Level
    {
        private Tile[][] tiles;

        /// <summary>
        /// 현재 세션 아이디
        /// </summary>
        private string sessionId;

        /// <summary>
        /// 현재 Level
        /// </summary>
        private int level;

        private string deepZoomUrl;

        public event EventHandler TileImageLoaded;

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="level"></param>
        public Level(string sessionId, int level, int width, int height, int horizontalTileCount, int verticalTileCount, string deepZoomUrl)
        {
            this.deepZoomUrl = deepZoomUrl;
            this.sessionId = sessionId;
            this.level = level;
            this.Width = width;
            this.Height = height;
            this.HorizontalTileCount = horizontalTileCount;
            this.VerticalTileCount = verticalTileCount;

            tiles = new Tile[VerticalTileCount][];

            for (int i = 0; i < VerticalTileCount; i++)
            {
                tiles[i] = new Tile[HorizontalTileCount];
            }

            for (int i = 0; i < verticalTileCount; i++)
            {
                for (int j = 0; j < horizontalTileCount; j++)
                {
                    tiles[i][j] = new Tile(sessionId, level, j, i, deepZoomUrl);
                }
            }
        }

        /// <summary>
        /// 레벨 Width
        /// </summary>
        public int Width { get; set; }

        /// <summary>
        /// 레벨 Height
        /// </summary>
        public int Height { get; set; }

        /// <summary>
        /// 가로 Tile 개수
        /// </summary>
        public int HorizontalTileCount { get; set; }

        /// <summary>
        /// 세로 Tile 개수
        /// </summary>
        public int VerticalTileCount { get; set; }

        public LoadState GetTileLoadState(int horizontalIndex, int verticalIndex)
        {
            return tiles[verticalIndex][horizontalIndex].LoadState;
        }

        /// <summary>
        /// Tile을 파일에서 로드합니다.
        /// 
        /// 만약 파일이 존재하지 않으면, 서버로부터 파일을 수신합니다.
        /// </summary>
        /// <param name="horizontalIndex"></param>
        /// <param name="verticalIndex"></param>
        /// <returns></returns>
        public Bitmap LoadTileImage(int horizontalIndex, int verticalIndex)
        {
            return tiles[verticalIndex][horizontalIndex].LoadImage();
        }

        /// <summary>
        /// Tile을 메모리에서 제거합니다.
        /// </summary>
        /// <param name="horizontalIndex"></param>
        /// <param name="verticalIndex"></param>
        public void UnloadTile(int horizontalIndex, int verticalIndex)
        {
            tiles[verticalIndex][horizontalIndex].CancelLoadRequest();
        }

        /// <summary>
        /// 타일을 요청합니다.
        /// </summary>
        /// <param name="horizontalIndex"></param>
        /// <param name="verticalIndex"></param>
        public void RequestTileASync(int horizontalIndex, int verticalIndex)
        {
            Tile tile = tiles[verticalIndex][horizontalIndex];

            if (tile.LoadState == LoadState.UnLoaded)
            {
                tile.LoadCompleted += new EventHandler(tile_LoadCompleted);

                tile.LoadRequest();
            }
            else
            {
                throw new Exception("Please debug error which is happened by a RequestTileASync method.");
            }
        }

        private void tile_LoadCompleted(object sender, EventArgs e)
        {
            Tile tile = (Tile)sender;

            tile.LoadCompleted -= new EventHandler(tile_LoadCompleted);

            if (this.TileImageLoaded != null)
                TileImageLoaded(this, null);
        }
    }
}
